/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package musicplayer;

import java.awt.Dimension;
import java.awt.Label;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.IOException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

/**
 *
 * @author Mr.D
 */
public class PlayList extends JFrame implements MouseListener, MouseMotionListener, Runnable, KeyListener{
    private JList songlist;
    private JScrollPane scrollpane;
    private String[] songname;
    private Manager manager;
    private JPopupMenu menu;
    private JMenuItem play, info, remove , removeother, removeall;
    private DefaultListModel modelname, modelurl;
    private int modelsize = 0, currentsongindex;
    private boolean deleted = false;
    private int oldx, oldy;
    private boolean changeposition, shuffle= false;
    private Label titlex, title;
    //Cac bien dung de shuffle
    private int[] arr;
    private boolean mark = true;
    private int num;
    private Random rd;
    private Toolkit tk;
    private Dimension screensize;
    private int frameposx = 0;
    private int frameposy = 0;
    private boolean directionx = false;
    private boolean directiony = false;
    private boolean isrunning = true;
    private boolean isholding = false;
    private boolean isbouchselected = false;
    private Thread mainthread;
    public PlayList(final Manager manager){
        super("JPlayList");
        this.manager = manager;
        setResizable(false);
        setBounds(0, 0, 300, 200);
        setAlwaysOnTop(true);
        setUndecorated(true);
        setLayout(null);
        mainthread = new Thread(this);
        tk  = Toolkit.getDefaultToolkit();
        screensize = tk.getScreenSize();
        rd = new Random();
        arr = new int[1];
        oldx = oldy = 0;
        changeposition = true;        
        titlex = new Label("x");
        titlex.setBounds(280, 0, 50, 20);
        title = new Label("JPlayList");
        title.setBounds(120, 0, 50, 20);
        title.setEnabled(false);
        menu = new JPopupMenu();
        play = new JMenuItem("Play Item");
        play.setToolTipText("Play selected item");
        info = new JMenuItem("File Info");
        info.setToolTipText("Show selected item information");
        remove = new JMenuItem("Remove");
        remove.setToolTipText("Remove selected item(s) from this list");
        removeother = new JMenuItem("Remove Other");
        removeother.setToolTipText("Remove unselect item(s) from this list");
        removeall = new JMenuItem("Remove All");
        removeall.setToolTipText("Remove all item from this list");
        modelname = new DefaultListModel();
        modelurl = new DefaultListModel();
        menu.add(play);
        menu.add(info);
        menu.add(remove);
        menu.add(removeother);
        menu.add(removeall);
        songname = new String[1];
        songname[0] = "";
        currentsongindex = -1;
        songlist = new JList(songname);
        songlist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        scrollpane = new JScrollPane(songlist);
        scrollpane.setBounds(0, 20, 300, getHeight()-20);       
        add(titlex);
        add(title);
        add(scrollpane);        
        songlist.addMouseListener(this);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        play.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if(songlist.getSelectedValue() != null){
                    currentsongindex = songlist.getSelectedIndex();
                    manager.processPopupMenu(1,songlist.getSelectedValue().toString(), modelurl.get(currentsongindex).toString());
                    if(shuffle){                       
                        contructShuffle();
                    }
                    updateInfo(false, 0);
                }
            }
        });
        info.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                updateInfo(true, 1);
            }
        });
        remove.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {                
                for(int i = songlist.getSelectedIndices().length; i > 0; i--){
                    if(songlist.getSelectedIndices()[i-1] < currentsongindex){
                        manager.processPopupMenu(5,"", "");
                        currentsongindex --;
                    }
                    else if(songlist.getSelectedIndices()[i-1] == currentsongindex)
                    {
                        manager.processPopupMenu(3,"", "");
                        deleted = true;
                    }
                    else
                        manager.processPopupMenu(5,"", "");
                    modelurl.removeElementAt(songlist.getSelectedIndices()[i-1]);
                    modelname.removeElementAt(songlist.getSelectedIndices()[i-1]);
                    modelsize --;
                }
                if(shuffle)
                    contructShuffle();


                
                //Cac dong duoi la danh cho lua 1 gia tri
//                if(songlist.getSelectedIndex() < currentsongindex){
//                    manager.processPopupMenu(5,songlist.getSelectedValue().toString(), modelurl.getElementAt(songlist.getSelectedIndex()).toString());
//                    currentsongindex --;
//                }
//                else if(songlist.getSelectedIndex() == currentsongindex)
//                {
//                    currentsongindex = songlist.getSelectedIndex() - 1;
//                    if(songlist.getSelectedIndex() == modelname.getSize() -1)
//                        currentsongindex = songlist.getSelectedIndex();
//                    manager.processPopupMenu(3,songlist.getSelectedValue().toString(), modelurl.getElementAt(songlist.getSelectedIndex()).toString());
//                }
//                else
//                    manager.processPopupMenu(5,songlist.getSelectedValue().toString(), modelurl.getElementAt(songlist.getSelectedIndex()).toString());
//                modelurl.remove(songlist.getSelectedIndex());
//                modelname.remove(songlist.getSelectedIndex());
//                modelsize --;
            }
        });
        removeother.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                modelsize = modelname.getSize();
                int[] selectedvalues = songlist.getSelectedIndices();
                int nextsongindex = modelname.getSize() - 1;
                boolean mark = false;
                for(int i = 0; i < modelsize; i++){
                    for(int j = 0; j < selectedvalues.length; j ++){
                        if(nextsongindex == selectedvalues[j]){
                            mark = true;
                            break;
                        }
                        else
                            mark = false;
                    }
                    if(mark == false){
                        if((nextsongindex < currentsongindex)){
                            manager.processPopupMenu(5, null, null);                            
                            modelname.removeElementAt(nextsongindex);
                            modelurl.removeElementAt(nextsongindex);
                            currentsongindex --;
                        }
                        else if(nextsongindex == currentsongindex){
                            manager.processPopupMenu(3, null, null);                                                        
                            modelname.removeElementAt(nextsongindex);
                            modelurl.removeElementAt(nextsongindex);                            
                            currentsongindex = -1;
                        }
                        else
                        {
                            manager.processPopupMenu(5, null, null);
                            modelname.removeElementAt(nextsongindex);
                            modelurl.removeElementAt(nextsongindex);
                        }
                    }
                    nextsongindex --;                    
                }
                modelsize = modelname.getSize();
                if(shuffle)
                    contructShuffle();
            }
        });
        removeall.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                manager.processPopupMenu(4, null, null);
                currentsongindex = -1;
                modelurl.removeAllElements();
                modelname.removeAllElements();
                modelsize = 0;
            }
        });
        titlex.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent e) {
                if(manager.isControlable())
                    setVisible(false);
            }

            public void mousePressed(MouseEvent e) {                
            }

            public void mouseReleased(MouseEvent e) {                
            }

            public void mouseEntered(MouseEvent e) {                
            }

            public void mouseExited(MouseEvent e) {                
            }
        });
    }
    public void updateInfo(boolean show, int song){
        if(song == 0)
            try {
            manager.showFileInfo(show, modelurl.getElementAt(currentsongindex).toString(), modelname.getElementAt(currentsongindex).toString());
        } catch (UnsupportedAudioFileException ex) {
            Logger.getLogger(PlayList.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(PlayList.class.getName()).log(Level.SEVERE, null, ex);
        }
        else
            try {
            manager.showFileInfo(show, modelurl.getElementAt(songlist.getSelectedIndex()).toString(), modelname.getElementAt(songlist.getSelectedIndex()).toString());
        } catch (UnsupportedAudioFileException ex) {
            Logger.getLogger(PlayList.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(PlayList.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public String listSong(){
        String listsong = "";
        for(int i = 0; i < modelname.getSize(); i++){
            listsong += modelname.getElementAt(i).toString()+"\n";
        }
        return listsong;
    }
    public String listUrl(){
        String listurl = "";
        for(int i = 0; i < modelurl.getSize(); i++){
            listurl += modelurl.getElementAt(i).toString()+"\n";
        }
        return listurl;
    }
    public String listCurrentSong(){
        String listsong = "";
        for(int i = 0; i < modelname.getSize(); i++){
            listsong += "Song "+(i+1)+" :"+modelname.getElementAt(i).toString()+"\n";
        }
        return listsong;
    }
    public String listCurrentUrl(){
        String listurl = "";
        for(int i = 0; i < modelurl.getSize(); i++){
            listurl += "Dir "+(i+1)+" :"+modelurl.getElementAt(i).toString()+"\n";
        }
        return listurl;
    }
    public String listAll(){
        String listall = "";
        for(int i = 0; i < modelurl.getSize(); i++){
            listall += "Path "+(i+1)+" :"+modelurl.getElementAt(i).toString()+modelname.getElementAt(i).toString()+"\n";
        }
        return listall;
    }
    public void setModelName(DefaultListModel model){
        modelname = model;
        songlist.setModel(modelname);
        if(!modelname.isEmpty())
            currentsongindex = 0;
    }
    public void setModelUrl(DefaultListModel model){
        for(int i = 0; i < model.size(); i++)
            modelurl.addElement(model.getElementAt(i));
    }
    public void addSong(String[] list, String url){        
        for(int i = 0; i < list.length; i++){
            modelname.addElement(list[i]);
            modelurl.addElement(url);
        }
        //currentsongindex =0;
        modelsize = modelname.getSize();
        songlist.setModel(this.modelname);
        if(shuffle)
            contructShuffle();        
    }
    public void addSong(String[] songlist){
        for(int i = 0; i < songlist.length; i++){
            System.out.println(songlist[i].toString());
            //modelname.addElement(songs[i]);
            //modelurl.addElement(url);
        }        
        //modelsize = modelname.getSize();
        //songlist.setModel(this.modelname);
        //if(shuffle)
            //contructShuffle();
    }
    public void setCurrentIndex(int index){
        this.currentsongindex = index;
    }
    public int getCurrentIndex(){
        return currentsongindex;
    }
    public int getPlayListLength(){
        return modelname.getSize();
    }
    public void gotoNextSong(){
        if(shuffle){
            for(int i = 0; i < modelname.getSize(); i++){
                if(currentsongindex == arr[i]){
                    if(i+1== modelname.getSize())
                        i--;
                    currentsongindex = arr[i+1];
                    break;
                }
            }
        }
        else{
            if((currentsongindex != -1)&&(deleted == false))
                currentsongindex ++;
            if(currentsongindex > (modelname.getSize()-1))
                currentsongindex = modelname.getSize()-1;            
        }
        manager.processPopupMenu(1,modelname.getElementAt(currentsongindex).toString(), modelurl.getElementAt(currentsongindex).toString());
        songlist.setSelectedIndex(currentsongindex);
        deleted = false;
        updateInfo(false, 0);
    }
    public void gotoPreviousSong(){
        if(shuffle){
            for(int i = 0; i < modelname.getSize(); i++){
                if(currentsongindex == arr[i]){
                    if(i == 0)
                        i =1;
                    currentsongindex = arr[i-1];
                    break;
                }
            }
        }
        else{
            if(currentsongindex != -1)
                currentsongindex --;
            if(currentsongindex < 0)
                currentsongindex = 0;            
        }
        manager.processPopupMenu(1,modelname.getElementAt(currentsongindex).toString(), modelurl.getElementAt(currentsongindex).toString());
        songlist.setSelectedIndex(currentsongindex);
        updateInfo(false, 0);
    }
    public boolean hasNext(){
        if(shuffle){
            if(currentsongindex == arr[modelname.getSize()-1])
                return false;
            else
                return true;
        }
        else{
            if(currentsongindex+1 < modelname.getSize())
                return true;
            else
                return false;
        }
    }
    public boolean hasPrevious(){
        if(shuffle){
            if(currentsongindex == arr[0])
                return false;
            else
                return true;
        }
        else{
            if(currentsongindex > 0)
                return true;
            else
                return false;
        }
    }
    public void PlayFirstSong(){
        manager.processPopupMenu(1,modelname.getElementAt(0).toString(), modelurl.getElementAt(0).toString());
        songlist.setSelectedIndex(0);
        updateInfo(false, 0);
        setCurrentIndex(0);
    }
    public void PlayLastSong(){
        manager.processPopupMenu(1,modelname.getElementAt(modelname.getSize()-1).toString(), modelurl.getElementAt(modelname.getSize()-1).toString());
        songlist.setSelectedIndex(modelname.getSize()-1);
        updateInfo(false, 0);
        setCurrentIndex(modelname.getSize()-1);
    }
    public void setShuffle(boolean state){
        this.shuffle = state;
    }
    public void contructShuffle() {
        arr = new int[modelname.getSize()];
        arr[0] = getCurrentIndex();
        for(int i = 1; i < modelname.getSize(); i++){
            mark = true;
            while(mark){
                mark = false;
                num = rd.nextInt(modelname.getSize());
                for(int j = 0; j < i; j++){
                    if(num == arr[j]){
                        mark = true;
                        break;
                    }
                }
                if((i == modelname.getSize()-1)&&(!mark)){
                    mark = false;
                }
            }
            arr[i] = num;

        }
        mark = true;
        while(mark){
            for(int i = 0; i < arr.length-2; i++){
                if(arr[i] != arr[i+1]){
                    mark = false;
                    break;
                }
            }
            if(mark)
                contructShuffle();
        }
        //In mang shuffle moi tao
        System.out.println();
        for(int j = 0; j < modelname.getSize(); j ++){
            System.out.print(arr[j]);
            if(j != modelname.getSize()-1)
                System.out.print(", ");
        }
    }
    public void mouseClicked(MouseEvent e) {
        if((e.getClickCount() == 2)&&(e.getButton()!= MouseEvent.BUTTON3)){
            if(songlist.getSelectedValue() != null){
                currentsongindex = songlist.getSelectedIndex();                
                manager.processPopupMenu(1,songlist.getSelectedValue().toString(), modelurl.getElementAt(songlist.getSelectedIndex()).toString());
                if(shuffle)
                    contructShuffle();
                updateInfo(false, 0);
            }
        }  
    }
    public void mousePressed(MouseEvent e) {
        oldx = e.getX();
        oldy = e.getY();        
        if(e.getButton() == MouseEvent.BUTTON3){
            menu.removeAll();
            if(songlist.getSelectedIndices().length == 0){
                menu.remove(play);
                menu.remove(info);
                menu.remove(remove);
                menu.remove(removeother);
                menu.add(removeall);
            }
            else if(songlist.getSelectedIndices().length == 1)
            {
                menu.add(play);
                menu.add(info);
                menu.add(remove);
                menu.add(removeother);
                menu.add(removeall);
            }
            else if(songlist.getSelectedIndices().length > 1)
            {
                menu.remove(play);
                menu.remove(info);
                menu.add(remove);
                menu.add(removeother);
                menu.add(removeall);
            }            
            if((songlist.getSelectedIndices().length == modelname.getSize())||(modelname.getSize() == 1)){
                menu.remove(removeother);
            }
            if(modelname.getSize() != 0)
                menu.show(this, getMousePosition().x, getMousePosition().y);
        }
        isholding = true;
    }

    public void mouseReleased(MouseEvent e) {
//        isholding = false;
    }

    public void mouseEntered(MouseEvent e) {
        isholding = true;
    }

    public void mouseExited(MouseEvent e) {
        isholding = false;
    }

    public void mouseDragged(MouseEvent e) {
        int newx = getX();
        int newy = getY();
        if(changeposition){
            if((getX() == 0)&&((e.getX()- oldx > 20)||(e.getX() - oldx < -20)))
                setLocation(e.getXOnScreen() - oldx, newy);
            if((getX() == (screensize.width - getWidth()))&&((oldx - e.getX() > 20)||(oldx - e.getX() < -20)))
                setLocation(oldx - e.getXOnScreen(), newy);
            if((getX() < 20)&&(getX() > - 20)){
                setLocation(0, newy);
            }
            else if((getX()+ getWidth() > screensize.width - 20)&&((getX()+ getWidth() < screensize.width + 20)))
                setLocation(screensize.width - getWidth(), newy);
            else{
                    setLocation(e.getXOnScreen() - oldx, newy);
            }
            changeposition = false;
        }
        else{
            if((getY() == 0)&&((e.getY()- oldy > 20)||(e.getY() - oldy < -20))){
                    setLocation(newx, e.getYOnScreen() - oldy);
            }
            if((getY() == (screensize.height - getHeight()))&&((oldy - e.getY() > 20)||(oldy - e.getY() < -20)))
                setLocation(newx, oldy - e.getYOnScreen());
            if((getY() < 20)&&(getY() > - 20)){
                    setLocation(newx, 0);
            }
            else if((getY()+ getHeight() > screensize.height - 20)&&((getY() + getHeight() < screensize.height + 20)))
                setLocation(newx, screensize.height - getHeight());
            else{
                    setLocation(newx, e.getYOnScreen() - oldy);
            }
            changeposition = true;
        }
        frameposx = getX();
        frameposy = getY();
    }
    public void mouseMoved(MouseEvent e) {
    }
    public void initialize(){
        mainthread.start();
        songlist.addMouseListener(this);
        songlist.addMouseMotionListener(this);
        scrollpane.addMouseListener(this);
        scrollpane.addMouseMotionListener(this);
        titlex.addMouseListener(this);
        titlex.addMouseMotionListener(this);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }
    public void setBouchState(boolean isbouchselected){
        this.isbouchselected = isbouchselected;
        frameposx = getX();
        frameposy = getY();
    }
    public void run(){
        while(isrunning){
            try{
                Thread.sleep(10);
            }
            catch(Exception e){}
            if(isbouchselected){
                if((frameposx + getWidth()) > screensize.width)
                    directionx = true;
                else if(frameposx < 0)
                    directionx = false;
                if((frameposy + getHeight()) > screensize.height)
                    directiony = true;
                else if(frameposy  < 0)
                    directiony = false;
                if(!isholding){
                    if(directionx)
                        frameposx --;
                    else
                        frameposx ++;
                    if(directiony)
                        frameposy --;
                    else
                        frameposy ++;
                }
                setLocation(frameposx, frameposy);
            }
        }
    }

    public void keyTyped(KeyEvent e) {

    }

    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
             setVisible(false);
    }

    public void keyReleased(KeyEvent e) {

    }
}
//Xu ly vi tri cua popupmenu
